package cn.jinjimi.app.main.widget.RollViewPager;

import android.content.Context;
import android.content.res.TypedArray;
import android.database.DataSetObserver;
import android.graphics.Color;
import android.graphics.drawable.GradientDrawable;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.Interpolator;
import android.widget.RelativeLayout;
import android.widget.Scroller;

import cn.jinjimi.app.R;
import cn.jinjimi.app.main.adapter.pagerAdapter.CyclePagerAdapter;

import java.lang.ref.WeakReference;
import java.lang.reflect.Field;

/**
 * Created by Roy
 * 支持自动轮播和提示的的viewpager
 * Date: 15/11/16
 */
public class RollPagerView extends RelativeLayout implements ViewPager.OnPageChangeListener, RollViewPager.onAttachedToWindowListener {

    private final static int HintViewPoint = 0;
    private final static int HintViewText = 1;
    private final static int HintViewNone = 2;

    private RollViewPager mViewPager;
    private CyclePagerAdapter mAdapter;
    private long mRecentTouchTime;
    //播放延迟
    private int delay;

    //hint位置
    private int gravity;

    //hint颜色
    private int color;

    //hint透明度
    private int alpha;

    // 是否无限循环
    private boolean isCycle;

    // 是否自动播放
    private boolean isAutoScroll;

    private int paddingLeft;
    private int paddingTop;
    private int paddingRight;
    private int paddingBottom;

    private View mHintView;

    private MyHandler mHandler;

    private Runnable mRunnable;

    private boolean showHintView = true;

    //根据数目来判断是否可以无限循环
    private boolean supportScrollCycleWithCounts = false;

    //是否支持循环，优先级大于根据数目来判断循环
    private boolean supportCycle = true;

    private int currentPositions = 0;

    @Override
    public void onAttach(int position) {
        setHintCurrent(position);

        //防止页面卡在中间的情况
        int pre = position - 1;
        pre = Math.max(0, pre);
        setCurrentItem(pre, false);
        setCurrentItem(position, false);
    }

    public interface onPagerChangeListener {
        void onPageSelected(int position);
    }

    private onPagerChangeListener onPagerChangeListener;

    public void setOnPagerChangeListener(onPagerChangeListener listener) {
        onPagerChangeListener = listener;
    }

    public RollPagerView(Context context) {
        this(context, null);
    }

    public RollPagerView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public RollPagerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView(attrs);
    }

    /**
     * 读取提示形式  和   提示位置   和   播放延迟
     *
     * @param attrs
     */
    private void initView(AttributeSet attrs) {
        if (mViewPager != null) {
            removeView(mViewPager);
        }

        TypedArray type = getContext().obtainStyledAttributes(attrs, R.styleable.RollViewPager);
        int mode = type.getInteger(R.styleable.RollViewPager_rollviewpager_hint_mode, HintViewPoint);    // 默认为point
        delay = type.getInt(R.styleable.RollViewPager_rollviewpager_play_delay, 3000);       // 默认3秒自动循环
        isCycle = type.getBoolean(R.styleable.RollViewPager_rollviewpager_play_cycle, true); // 默认无限循环
        isAutoScroll = type.getBoolean(R.styleable.RollViewPager_rollviewpager_play_auto, true);// 默认自动播放

        gravity = type.getInteger(R.styleable.RollViewPager_rollviewpager_hint_gravity, 2);  // 默认居右显示
        color = type.getColor(R.styleable.RollViewPager_rollviewpager_hint_color, Color.BLACK);
        alpha = type.getInt(R.styleable.RollViewPager_rollviewpager_hint_alpha, 0);

        paddingLeft = (int) type.getDimension(R.styleable.RollViewPager_rollviewpager_hint_paddingLeft, 0);
        paddingRight = (int) type.getDimension(R.styleable.RollViewPager_rollviewpager_hint_paddingRight, getContext().getResources().getDimensionPixelSize(R.dimen.dp_5));
        paddingTop = (int) type.getDimension(R.styleable.RollViewPager_rollviewpager_hint_paddingTop, 0);
        paddingBottom = (int) type.getDimension(R.styleable.RollViewPager_rollviewpager_hint_paddingBottom, getContext().getResources().getDimensionPixelSize(R.dimen.dp_5));

        mViewPager = new RollViewPager(getContext());
        mViewPager.setId(R.id.viewpager_inner);
        mViewPager.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
        addView(mViewPager);
        type.recycle();

        initHint(mode);
    }

    /**
     * 设置viewager滑动动画持续时间
     *
     * @param during
     */
    public void setAnimationDurtion(final int during) {
        try {
            // viePager平移动画事件
            Field mField = ViewPager.class.getDeclaredField("mScroller");
            mField.setAccessible(true);
            Scroller mScroller = new Scroller(getContext(),
                    // 动画效果与ViewPager的一致
                    new Interpolator() {
                        public float getInterpolation(float t) {
                            t -= 1.0f;
                            return t * t * t * t * t + 1.0f;
                        }
                    }) {

                @Override
                public void startScroll(int startX, int startY, int dx,
                                        int dy, int duration) {
                    // 如果手工滚动,则加速滚动
                    if (System.currentTimeMillis() - mRecentTouchTime > delay) {
                        duration = during;
                    } else {
                        duration /= 2;
                    }
                    super.startScroll(startX, startY, dx, dy, duration);
                }

                @Override
                public void startScroll(int startX, int startY, int dx,
                                        int dy) {
                    super.startScroll(startX, startY, dx, dy, during);
                }
            };
            mField.set(mViewPager, mScroller);
        } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
            e.printStackTrace();
        }
    }

    /* 设置是否自动播放 */
    public void setAutoScroll(boolean isAutoScroll) {
        this.isAutoScroll = isAutoScroll;
        startPlay();
    }

    /* 设置Adapter */
    public void setAdapter(CyclePagerAdapter adapter) {
        adapter.setSupportCycle(supportCycle);
        mViewPager.setAdapter(adapter);
        mViewPager.addOnPageChangeListener(this);
        mViewPager.setAttachedToWindowListener(this);
        mAdapter = adapter;
        if (supportCycle) {
            if (adapter.getItemsSize() < 2) {
                supportScrollCycleWithCounts = false;
                setAutoScroll(false);
            } else {
                supportScrollCycleWithCounts = true;
                setAutoScroll(true);
                setCurrentItem(0, false);// 支持开始的右滑
            }
        } else {
            setAutoScroll(false);
        }
        dataSetChanged();
        adapter.registerDataSetObserver(new JPagerObserver());
    }

    /* 用来实现adapter的notifyDataSetChanged通知HintView变化 */
    private class JPagerObserver extends DataSetObserver {
        @Override
        public void onChanged() {
            dataSetChanged();
        }

        @Override
        public void onInvalidated() {
            dataSetChanged();
        }
    }

    private void dataSetChanged() {
        startPlay();
        if (mHintView != null && showHintView) {
            ((HintView) mHintView).initView(mAdapter.getItemsSize(), gravity);
            if (mAdapter.getItemsSize() < 2) { // 小于2个时不显示下标
                mHintView.setVisibility(View.GONE);
            } else {
                mHintView.setVisibility(View.VISIBLE);
            }
        }
    }

    /**
     * 开始播放
     * 仅当view正在显示 且 触摸等待时间过后 播放
     */
    private void startPlay() {
        if (delay <= 0 || mAdapter.getItemsSize() <= 1) {
            return;
        }
        if (mHandler != null && mRunnable != null) {
            mHandler.removeCallbacks(mRunnable);
        }

        if (!isAutoScroll) return;

        mHandler = new MyHandler(this);
        mRunnable = new MyRunnable(this);
        mHandler.postDelayed(mRunnable, delay);
    }

    private static class MyHandler extends Handler {
        private WeakReference<RollPagerView> mRPVWeakReference;
        int cur;

        public MyHandler(RollPagerView mRollPagerView) {
            this.mRPVWeakReference = new WeakReference<>(mRollPagerView);
        }

        @Override
        public void handleMessage(Message msg) {
            RollPagerView rollPagerView = mRPVWeakReference.get();
            if (rollPagerView != null) {
                cur = rollPagerView.getViewPager().getCurrentItem() + 1;
                if (rollPagerView.mAdapter != null
                        && cur >= rollPagerView.mAdapter.getCount()) {
                    cur = 0;
                }
                rollPagerView.getViewPager().setCurrentItem(cur);
                rollPagerView.setHintCurrent(cur);
            }
        }
    }

    private static class MyRunnable implements Runnable {
        private WeakReference<RollPagerView> mRPVWeakReference;

        public MyRunnable(RollPagerView mRollPagerView) {
            this.mRPVWeakReference = new WeakReference<>(mRollPagerView);
        }

        @Override
        public void run() {
            RollPagerView rollPagerView = mRPVWeakReference.get();
            if (rollPagerView != null) {
                if (rollPagerView.isShown() && rollPagerView.hasWindowFocus()
                        && System.currentTimeMillis() - rollPagerView.mRecentTouchTime > rollPagerView.delay) {
                    rollPagerView.mHandler.sendEmptyMessage(0);
                }
                rollPagerView.mHandler.postDelayed(this, rollPagerView.delay);
            }
        }
    }

    ;

    /**
     * 为了实现触摸时和过后一定时间内不滑动
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        mRecentTouchTime = System.currentTimeMillis();
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void onPageScrollStateChanged(int state) {
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
    }

    @Override
    public void onPageSelected(int position) {
        currentPositions = position;
        if (null != onPagerChangeListener) {
            onPagerChangeListener.onPageSelected(getRealPosition(position));
        }
        setHintCurrent(position);
    }

    private int getRealPosition(int p) {
        int position = p % mAdapter.getItemsSize();
        if (position < 0) {
            position = mAdapter.getItemsSize() + position;
        }
        return position;
    }

    /* Hint管理模块 */

    /**
     * 设置提示view
     *
     * @param mode
     */
    private void initHint(int mode) {
        switch (mode) {
            case HintViewPoint:
                initHint(new PointHintView(getContext()));
                break;
            case HintViewText:
                initHint(new TextHintView(getContext()));
                break;
            case HintViewNone:
                break;
            default:
                break;
        }
    }

    private void initHint(HintView hintview) {
        if (mHintView != null) {
            removeView(mHintView);
        }

        if (hintview == null || !(hintview instanceof HintView)) {
            return;
        }

        mHintView = (View) hintview;
        loadHintView();
    }

    /**
     * 加载hintview的容器
     */
    private void loadHintView() {
        addView(mHintView);
        mHintView.setPadding(paddingLeft, paddingTop, paddingRight, paddingBottom);
        LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
        mHintView.setLayoutParams(lp);

        GradientDrawable gd = new GradientDrawable();
        gd.setColor(color);
        gd.setAlpha(alpha);
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            mHintView.setBackgroundDrawable(gd);
        } else {
            mHintView.setBackground(gd);
        }

        ((HintView) mHintView).initView(mAdapter == null ? 0 : mAdapter.getItemsSize(), gravity);
    }

    public void setHintCurrent(int position) {
        if (mHintView != null) {
            if (isCycle) {
                position %= mAdapter.getItemsSize();
                if (position < 0) {
                    position = mAdapter.getItemsSize() + position;
                }
            }
            ((HintView) mHintView).setCurrent(position);
        }
    }

    public void setHintViewVisibility(boolean visibility) {
        showHintView = visibility;
        if (mHintView != null) {
            mHintView.setVisibility(visibility ? VISIBLE : GONE);
        }
    }

    /**
     * 设置提示view的透明度
     *
     * @param alpha 0为全透明  255为实心
     */
    public void setHintAlpha(int alpha) {
        this.alpha = alpha;
        initHint((HintView) mHintView);
    }

    /**
     * 支持自定义hintview
     * 只需new一个实现HintView的View传进来
     * 会自动将你的view添加到本View里面。重新设置LayoutParams。
     *
     * @param hintview
     */
    public void setHintView(HintView hintview) {
        if (!(hintview instanceof View)) {
            throw new IllegalArgumentException("HintView should be a View");
        }
        this.mHintView = (View) hintview;
        initHint(hintview);
    }

    /**
     * 取真正的Viewpager
     *
     * @return
     */
    public ViewPager getViewPager() {
        return mViewPager;
    }

    public void setCurrentItem(int position) {
        setCurrentItem(position, true);
    }


    public void setCurrentItem(int position, boolean anim) {
        int offset = 0;
        if (supportScrollCycleWithCounts) {
            offset = mAdapter.getItemsSize() * 100;
        }
        currentPositions = offset + position;
        mViewPager.setCurrentItem(currentPositions, anim);
    }

    //加载下一个页面
    public void next() {
        currentPositions++;
        mViewPager.setCurrentItem(currentPositions);
    }

    //加载前一个页面
    public void previous() {
        currentPositions--;
        if (currentPositions < 0) {
            currentPositions = getRealPosition(currentPositions);
        }
        mViewPager.setCurrentItem(currentPositions);

    }

    //调用setAdapter之前调用
    public void setSupportCycle(boolean supportCycle) {
        this.supportCycle = supportCycle;
    }
}